Modify CR0 access emulation -- return physical CR0 (except
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 23 Dec 2005 15:42:46 +0000 (16:42 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 23 Dec 2005 15:42:46 +0000 (16:42 +0100)
for TS) and allow only the same physical flags to be written
back to CR0 by a guest.

Add write-to-CR4 emulation, but check that the write does not
modify any CR4 flags.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/traps.c

index 8e1ca7f579e3547ab36137092d955e795c1db5fa..40959e6758c224ec067584ddf6fa12eb83f9186a 100644 (file)
@@ -885,7 +885,8 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
         switch ( modrm_reg )
         {
         case 0: /* Read CR0 */
-            *reg = v->arch.guest_context.ctrlreg[0];
+            *reg = (read_cr0() & ~X86_CR0_TS) |
+                v->arch.guest_context.ctrlreg[0];
             break;
 
         case 2: /* Read CR2 */
@@ -927,6 +928,11 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
         switch ( modrm_reg )
         {
         case 0: /* Write CR0 */
+            if ( (*reg ^ read_cr0()) & ~X86_CR0_TS )
+            {
+                DPRINTK("Attempt to change unmodifiable CR0 flags.\n");
+                goto fail;
+            }
             (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
             break;
 
@@ -941,6 +947,14 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
             UNLOCK_BIGLOCK(v->domain);
             break;
 
+        case 4:
+            if ( *reg != (read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE)) )
+            {
+                DPRINTK("Attempt to change CR4 flags.\n");
+                goto fail;
+            }
+            break;
+
         default:
             goto fail;
         }